package asf.forms
{
	import flash.utils.*;

	dynamic public class FormFields extends Proxy
	{
		protected var raw:XML;
		private var dict:Object;
		private var items:Array;
		protected var source:XML;
		
		public function FormFields( p_raw:XML, p_sourceXML:XML )
		{
			super( );
			
			raw = p_raw;
			source = p_sourceXML;
			
			parse( );
		}
		
		public function getRawXML( ):XML
		{
			return raw.copy( );
		}
		
		private function parse( ):void
		{
			var fieldItem:XML;
			var field:FormField;
			var tabIndex:uint = 0;
			
			dict = new Object( );
			items = new Array( );
			
			for each( fieldItem in source.field )
			{
				field = new FormField( fieldItem );
				field.view.setTabIndex( tabIndex ++ );
				
				items.push( field );
				dict[ field.id ] = field;
			}
		}
		
		public function getErrors( ):Array
		{
			var result:Array = new Array( );
			var field:FormField;
			var validation:FormFieldError;
			
			for each( field in items )
			{
				validation = getFieldValidation( field.id );
				
				if( validation != null )
				{
					result.push( validation );
				}
			}
			
			return result;
		}
		
		public function isFieldValid( fieldID:String ):Boolean
		{
			return ( getFieldValidation( fieldID ) == null );
		}
		
		public function getFieldValidation( fieldID:String ):FormFieldError
		{
			var field:FormField = getField( fieldID );
			
			if( field.view.isEmpty( ) && field.required )
			{
				return new FormFieldError( field, field.requiredMessage, FormFieldErrorType.REQUIRED ); 
			}
			else if( !field.view.isValid( ) || !field.isValidRegExp( ) )
			{
				return new FormFieldError( field, field.invalidMessage, FormFieldErrorType.INVALID );
			}
			
			if( field.matchID != "" )
			{
				if( getField( field.matchID ).getValue( ) != field.getValue( ) )
				{
					return new FormFieldError( field, field.mismatchMessage, FormFieldErrorType.MISMATCH );
				}
			}
			
			return null;
		}
		
		public function markAllErrors( typeFilter:String = "" ):void
		{
			var error:FormFieldError;
			var field:FormField;
			
			for each( field in items )
			{
				error = getFieldValidation( field.id );
				
				if( error != null )
				{
					if( typeFilter == "" || error.type == typeFilter )
					{
						field.view.markError( error.message );
					}
				}
				else
				{
					field.view.clearError( );
				}
			}
		}
		
		public function clearAllErrors( ):void
		{
			var field:FormField;
			
			for each( field in items )
			{
				field.view.clearError( );
			}
		}
		
		public function disableAll( ):void
		{
			var field:FormField;
			
			for each( field in items )
			{
				field.view.disable( );
			}
		}
		
		public function enableAll( ):void
		{
			var field:FormField;
			
			for each( field in items )
			{
				field.view.enable( );
			}
		}
		
		public function disableField( fieldID:String ):void
		{
			this.getField( fieldID ).disable( );
		}
		
		public function enableField( fieldID:String ):void
		{
			this.getField( fieldID ).enable( );
		}
		
		public function getResult( ):Object
		{
			var field:FormField;
			var result:Object = new Object( );
			
			for each( field in items )
			{
				result[ field.id ] = field.getValue( );
			}
			
			return result;
		}
		
		public function isValid( ):Boolean
		{
			return getErrors( ).length == 0;
		}
		
		public function getFields( ):Array
		{
			return [ ].concat( items );
		}
		
		override flash_proxy function getProperty( name:* ):*
		{
			return getField( name );
		}
		
		public function getField( fieldID:String ):FormField
		{
			return dict[ fieldID ];
		}
		
		public function dispose( ):void
		{
			items = null;
			dict = null;
			
			raw = null;
			source = null;
		}
	}
}